/* *****************************************************************************
 * JFab (http://code.google.com/p/jfab)
 * Copyright (c) 2011 JFab.org
 * Admin jfab@jeffreythompson.net
 *
 * See the file "LICENSE.txt" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * *****************************************************************************/

package org.jfab.core.inflator;

import java.util.Comparator;
import java.util.List;

import org.apache.commons.lang3.Validate;
import org.jfab.core.collection.CGAnnotationList;
import org.jfab.core.collection.CGConstructorList;
import org.jfab.core.collection.CGEnumItemList;
import org.jfab.core.collection.CGFieldList;
import org.jfab.core.collection.CGInitializationBlockList;
import org.jfab.core.collection.CGInterfaceList;
import org.jfab.core.collection.CGMethodList;
import org.jfab.core.collection.CGTypeList;
import org.jfab.core.collection.CommentList;
import org.jfab.core.collection.ModifierList;
import org.jfab.core.factory.CGConstructorFactory;
import org.jfab.core.factory.CGEnumFactory;
import org.jfab.core.factory.CGFieldFactory;
import org.jfab.core.factory.CGMethodFactory;
import org.jfab.core.factory.CGParameterFactory;
import org.jfab.core.factory.CGTypeFactory;
import org.jfab.core.factory.StringFactory;
import org.jfab.core.model.CGConstructor;
import org.jfab.core.model.CGEnum;
import org.jfab.core.model.CGField;
import org.jfab.core.model.CGMethod;
import org.jfab.core.model.CGTypeUtilities;
import org.jfab.core.model.Modifier;
import org.jfab.core.util.TypeParameterMap;

/**
 * Provides a default implementation of a code generator enum inflator.
 */
public final class DefaultCGEnumInflator extends CGConcreteUnitInflator<CGEnum>
        implements CGEnumInflator
{
    /** Enum factory. */
    private final CGEnumFactory _enumFactory;

    /**
     * Construct this object with the given parameters.
     * 
     * @param stringFactory String factory. (required)
     * @param cgTypeUtils Code generator type utilities. (required)
     * @param cgTypeFactory Code generator type factory. (required)
     * @param fieldFactory Field factory. (required)
     * @param fieldComparator Field comparator. (required)
     * 
     * @param parameterFactory Parameter factory. (required)
     * @param constructorFactory Constructor factory. (required)
     * @param constructorComparator Constructor comparator. (required)
     * @param methodFactory Method factory. (required)
     * @param methodComparator Method comparator. (required)
     * 
     * @param enumFactory Enum factory. (required)
     */
    public DefaultCGEnumInflator(final StringFactory stringFactory,
            final CGTypeUtilities cgTypeUtils,
            final CGTypeFactory cgTypeFactory,
            final CGFieldFactory fieldFactory,
            final Comparator<CGField> fieldComparator,
            final CGParameterFactory parameterFactory,
            final CGConstructorFactory constructorFactory,
            final Comparator<CGConstructor> constructorComparator,
            final CGMethodFactory methodFactory,
            final Comparator<CGMethod> methodComparator,
            final CGEnumFactory enumFactory)
    {
        super(stringFactory, cgTypeUtils, cgTypeFactory, fieldFactory,
                fieldComparator, parameterFactory, constructorFactory,
                constructorComparator, methodFactory, methodComparator);

        Validate.notNull(enumFactory, "enumFactory is null");

        _enumFactory = enumFactory;
    }

    @Override
    public final CGEnum inflate(final CGEnum cgEnum,
            final CGInterfaceList superInterfaces)
    {
        final CGTypeList referencedTypes = new CGTypeList(
                cgEnum.getReferencedTypes());
        final String packageName = cgEnum.getPackageName();
        final CommentList commentLines = new CommentList(
                cgEnum.getCommentLines());
        final CGAnnotationList annotations = new CGAnnotationList(
                cgEnum.getAnnotations());
        final ModifierList modifiers = new ModifierList(cgEnum.getModifiers());
        final String enumName = cgEnum.getName();
        final List<String> typeParameters = cgEnum.getTypeParameters();
        final CGEnumItemList enumItems = new CGEnumItemList(
                cgEnum.getEnumItems());
        final TypeParameterMap typeParameterMap = createTypeParameterMap(
                cgEnum, superInterfaces);
        final CGInitializationBlockList initializationBlocks = new CGInitializationBlockList(
                cgEnum.getInitializationBlocks());
        final CGFieldList fields = createFields(cgEnum, superInterfaces,
                typeParameterMap);
        final ModifierList constructorModifiers = new ModifierList(
                Modifier.PRIVATE);
        final CGConstructorList constructors = createConstructors(
                constructorModifiers, cgEnum, fields);
        final CGMethodList methods = createMethods(cgEnum, fields);

        return getEnumFactory().createEnum(referencedTypes, packageName,
                commentLines, annotations, modifiers, enumName, typeParameters,
                enumItems, initializationBlocks, constructors, fields, methods);
    }

    /**
     * @param cgEnum Code generator enum.
     * @param inflatedFields Inflated fields.
     * 
     * @return new methods created from the given parameter.
     */
    protected final CGMethodList createMethods(final CGEnum cgEnum,
            final CGFieldList inflatedFields)
    {
        final CGMethodList answer = new CGMethodList();

        super.createMethods(answer, cgEnum, inflatedFields);

        return answer;
    }

    @Override
    protected final TypeParameterMap createTypeParameterMap(
            final CGEnum cgObject, final CGInterfaceList superInterfaces)
    {
        return null;
    }

    /**
     * @return the enumFactory
     */
    private CGEnumFactory getEnumFactory()
    {
        return _enumFactory;
    }
}
